home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / BasicSliderUI.java < prev    next >
Text File  |  1998-06-30  |  44KB  |  1,390 lines

  1. /*
  2.  * @(#)BasicSliderUI.java    1.54 98/02/04
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.plaf.basic;
  22.  
  23. import java.awt.Component;
  24. import java.awt.Container;
  25. import java.awt.Adjustable;
  26. import java.awt.event.AdjustmentListener;
  27. import java.awt.event.AdjustmentEvent;
  28. import java.awt.event.ActionListener;
  29. import java.awt.event.ActionEvent;
  30. import java.awt.event.MouseMotionListener;
  31. import java.awt.event.MouseAdapter;
  32. import java.awt.event.MouseEvent;
  33. import java.awt.event.ComponentListener;
  34. import java.awt.event.ComponentEvent;
  35. import java.awt.event.FocusListener;
  36. import java.awt.event.FocusEvent;
  37. import java.awt.event.KeyEvent;
  38. import java.awt.Graphics;
  39. import java.awt.Dimension;
  40. import java.awt.Rectangle;
  41. import java.awt.Point;
  42. import java.awt.Insets;
  43. import java.awt.Color;
  44. import java.io.Serializable;
  45. import java.awt.IllegalComponentStateException;
  46. import java.awt.Polygon;
  47. import java.beans.*;
  48. import java.util.*;
  49.  
  50. import com.sun.java.swing.border.AbstractBorder;
  51.  
  52. import com.sun.java.swing.*;
  53. import com.sun.java.swing.event.*;
  54. import com.sun.java.swing.plaf.*;
  55.  
  56.  
  57. /**
  58.  * A Basic L&F implementation of SliderUI.  
  59.  * <p>
  60.  * Warning: serialized objects of this class will not be compatible with
  61.  * future swing releases.  The current serialization support is appropriate 
  62.  * for short term storage or RMI between Swing1.0 applications.  It will
  63.  * not be possible to load serialized Swing1.0 objects with future releases
  64.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  65.  * baseline for the serialized form of Swing objects.
  66.  *
  67.  * @version 1.54 02/04/98
  68.  * @author David Kloba
  69.  * @author Tom Santos
  70.  */
  71. public class BasicSliderUI extends SliderUI implements Serializable, PropertyChangeListener
  72. {
  73.     // Public
  74.     public final int POSITIVE_SCROLL = +1;
  75.     public final int NEGATIVE_SCROLL = -1;
  76.     public final int MIN_SCROLL = -2;
  77.     public final int MAX_SCROLL = +2;
  78.  
  79.     // Protected
  80.     protected ScrollListener scrollListener;
  81.     protected Timer scrollTimer;
  82.     protected JSlider slider;
  83.     protected Rectangle labelRect = new Rectangle( 0, 0, 0, 0 );
  84.     protected int trackBuffer = 0;  // The distance that the track is from the side of the control
  85.  
  86.     // Static private
  87.     private static final int TICK_SPACE = 8;
  88.     private static final Dimension PREFERRED_HORIZONTAL_SIZE = new Dimension(164, 21);
  89.     private static final Dimension PREFERRED_VERTICAL_SIZE = new Dimension(21, 164);
  90.     private static final Dimension MINIMUM_HORIZONTAL_SIZE = new Dimension(36, 21);
  91.     private static final Dimension MINIMUM_VERTICAL_SIZE = new Dimension(21, 36);
  92.  
  93.     // Private
  94.     private transient boolean isDragging;
  95.     private TrackListener trackListener;
  96.     private ModelListener modelListener;
  97.     private SizingListener sizeListener;
  98.     private FListener focusListener;
  99.     private Rectangle thumbRect = new Rectangle(0, 0, 0, 0);
  100.  
  101.     // Colors
  102.     private Color shadowColor;
  103.     private Color highlightColor;
  104.     private Color focusColor;
  105.  
  106.     public Color getShadowColor() {
  107.     return shadowColor;
  108.     }
  109.  
  110.     public Color getHighlightColor() {
  111.     return highlightColor;
  112.     }
  113.  
  114.     public Color getFocusColor() {
  115.     return focusColor;
  116.     }
  117.  
  118.     /////////////////////////////////////////////////////////////////////////////
  119.     // ComponentUI Interface Implementation methods
  120.     /////////////////////////////////////////////////////////////////////////////
  121.     public static ComponentUI createUI(JComponent b)    {
  122.         return new BasicSliderUI((JSlider)b);
  123.     }
  124.  
  125.     public BasicSliderUI(JSlider b)   {
  126.     }
  127.             
  128.     public void installUI(JComponent c)   {
  129.     slider = (JSlider) c;
  130.  
  131.         LookAndFeel.installBorder(slider, "Slider.border");
  132.         LookAndFeel.installColors(slider, "Slider.background", "Slider.foreground");
  133.     highlightColor = UIManager.getColor("Slider.highlight");
  134.     shadowColor = UIManager.getColor("Slider.shadow");
  135.     focusColor = UIManager.getColor("Slider.focus");
  136.  
  137.     isDragging = false;
  138.     trackListener = new TrackListener();
  139.     modelListener = new ModelListener();
  140.     sizeListener = new SizingListener();
  141.     focusListener = new FListener();
  142.     scrollListener = new ScrollListener();
  143.     scrollTimer = new Timer(100, scrollListener);
  144.     scrollTimer.setInitialDelay(300);    
  145.     
  146.         slider.addMouseListener(trackListener);
  147.         slider.addMouseMotionListener(trackListener);
  148.         slider.addFocusListener(focusListener);
  149.     slider.addComponentListener(sizeListener);
  150.     slider.addPropertyChangeListener(this);
  151.         slider.getModel().addChangeListener(modelListener);
  152.     slider.setEnabled(slider.isEnabled());
  153.     slider.setOpaque(true);
  154.  
  155.     // I calculate the thumb bounds twice here because the recalc* methods need to know
  156.     // the dimensions of the thumb and then to get the final correct thumb bounds, I need
  157.     // to calculate again after the recalc* methods have been called.  This is obviously
  158.     // rediculous, but I don't have the time to change the way that everything is calculated.
  159.     calculateThumbBounds();
  160.     recalcLabelRect();
  161.     recalcTrackBuffer();
  162.     calculateThumbBounds();
  163.             
  164.         slider.registerKeyboardAction(new ActionScroller(slider, POSITIVE_SCROLL, false),
  165.         KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0), 
  166.         JComponent.WHEN_FOCUSED);
  167.         slider.registerKeyboardAction(new ActionScroller(slider, NEGATIVE_SCROLL, false),
  168.         KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0), 
  169.         JComponent.WHEN_FOCUSED);
  170.         slider.registerKeyboardAction(new ActionScroller(slider, NEGATIVE_SCROLL, true),
  171.                 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN,0), 
  172.         JComponent.WHEN_FOCUSED);
  173.         slider.registerKeyboardAction(new ActionScroller(slider, NEGATIVE_SCROLL, false),
  174.                 KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0), 
  175.         JComponent.WHEN_FOCUSED);
  176.         slider.registerKeyboardAction(new ActionScroller(slider, POSITIVE_SCROLL, false),
  177.                 KeyStroke.getKeyStroke(KeyEvent.VK_UP,0), 
  178.         JComponent.WHEN_FOCUSED);
  179.         slider.registerKeyboardAction(new ActionScroller(slider, POSITIVE_SCROLL, true),
  180.                 KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP,0), 
  181.         JComponent.WHEN_FOCUSED);
  182.         slider.registerKeyboardAction(new ActionScroller(slider, MIN_SCROLL, true),
  183.                 KeyStroke.getKeyStroke(KeyEvent.VK_HOME,0), 
  184.         JComponent.WHEN_FOCUSED);
  185.         slider.registerKeyboardAction(new ActionScroller(slider, MAX_SCROLL, true),
  186.                 KeyStroke.getKeyStroke(KeyEvent.VK_END,0), 
  187.         JComponent.WHEN_FOCUSED);
  188.     }   
  189.  
  190.     public void uninstallUI(JComponent c) {
  191.     if(c != slider)
  192.         throw new IllegalComponentStateException(
  193.         this + " was asked to deinstall() " 
  194.         + c + " when it only knows about " 
  195.         + slider + "."); 
  196.  
  197.         LookAndFeel.uninstallBorder(slider);
  198.  
  199.     scrollTimer.stop();
  200.     scrollTimer = null;
  201.         
  202.         slider.getModel().removeChangeListener(modelListener);
  203.         slider.removeMouseListener(trackListener);
  204.         slider.removeMouseMotionListener(trackListener);
  205.         slider.removeFocusListener(focusListener);
  206.     slider.removeComponentListener(sizeListener);
  207.     slider.removePropertyChangeListener(this);
  208.         slider.resetKeyboardActions();
  209.                 
  210.     thumbRect = null;
  211.     slider = null;
  212.     }
  213.  
  214.     public Dimension getPreferredHorizontalSize() {
  215.     return PREFERRED_HORIZONTAL_SIZE;
  216.     }
  217.  
  218.     public Dimension getPreferredVerticalSize() {
  219.     return PREFERRED_VERTICAL_SIZE;
  220.     }
  221.  
  222.     public Dimension getMinimumHorizontalSize() {
  223.     return MINIMUM_HORIZONTAL_SIZE;
  224.     }
  225.  
  226.     public Dimension getMinimumVerticalSize() {
  227.     return MINIMUM_VERTICAL_SIZE;
  228.     }
  229.  
  230.  
  231.  
  232.     public Dimension getPreferredSize(JComponent c)    {
  233.     Dimension d;
  234.         if (slider.getOrientation() == JSlider.VERTICAL) {
  235.         d = new Dimension(getPreferredVerticalSize());
  236.         if(slider.getPaintTicks()) {
  237.         d.width += getScrollTickRect().width + 1;
  238.         }
  239.         if ( slider.getPaintLabels() ) {
  240.             d.width += getLabelRect().width + 1;
  241.         }
  242.         } else {
  243.         d = new Dimension(getPreferredHorizontalSize());
  244.         if(slider.getPaintTicks()) {
  245.         d.height += getScrollTickRect().height + 1;
  246.         }
  247.         if ( slider.getPaintLabels() ) {
  248.             d.height += getLabelRect().height + 1;
  249.         }
  250.         }
  251.         d.width += slider.getInsets().left + slider.getInsets().right;
  252.         d.height += slider.getInsets().top + slider.getInsets().bottom;
  253.  
  254.         return d;
  255.     }
  256.     
  257.     public Dimension getMinimumSize(JComponent c)  {
  258.     Dimension d;
  259.  
  260.         if (slider.getOrientation() == JSlider.VERTICAL) {
  261.         d = new Dimension(getMinimumVerticalSize());
  262.         if(slider.getPaintTicks()) {
  263.         d.width += getTickSpace() + 1;
  264.         }
  265.         if ( slider.getPaintLabels() ) {
  266.             d.width += getLabelRect().width + 1;
  267.         }
  268.         } else {
  269.         d = new Dimension(getMinimumHorizontalSize());
  270.         if(slider.getPaintTicks()) {
  271.         d.height += getTickSpace() + 1;
  272.         }
  273.         if ( slider.getPaintLabels() ) {
  274.             d.height += getLabelRect().height + 1;
  275.         }
  276.         }
  277.  
  278.  
  279.         d.width += slider.getInsets().left + slider.getInsets().right;
  280.         d.height += slider.getInsets().top + slider.getInsets().bottom;
  281.  
  282.         return d;
  283.     }
  284.     
  285.     public Dimension getMaximumSize(JComponent c) {
  286.     Dimension d = getPreferredSize(c);
  287.         if (slider.getOrientation() == JSlider.VERTICAL) {
  288.         d.height = Short.MAX_VALUE;
  289.     } else {
  290.         d.width = Short.MAX_VALUE;
  291.     }
  292.  
  293.     return d;
  294.     }
  295.    
  296.     protected Rectangle getFullContentArea() {
  297.     Rectangle r = new Rectangle();
  298.     Insets insets = slider.getInsets();
  299.     Dimension size = slider.getSize();
  300.  
  301.     r.x = insets.left;
  302.     r.y = insets.top;
  303.     r.width = size.width - (insets.left + insets.right);
  304.     r.height = size.height - (insets.top + insets.bottom);
  305.  
  306.     return r;
  307.     }
  308.  
  309.     public Rectangle getScrollTrackRect() {
  310.         Rectangle r = getFullContentArea();
  311.  
  312.     if ( slider.getPaintTicks() || slider.getPaintLabels() ) {
  313.         if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  314.             r.setSize( r.width, (getScrollTickRect().y - 1) - r.y );
  315.         }
  316.         else {
  317.             r.setSize( (getScrollTickRect().x - 1) - r.x, r.height );
  318.         }
  319.     }
  320.  
  321.     return r;
  322.     }
  323.  
  324.     public Rectangle getScrollTickRect() {
  325.     Rectangle r = getFullContentArea();
  326.     
  327.     if(slider.getPaintTicks())  {
  328.  
  329.         Rectangle labelRect = getLabelRect();
  330.  
  331.         if(slider.getOrientation() == JSlider.VERTICAL)  {
  332.             if ( slider.getPaintLabels() ) {
  333.             r.setLocation( (labelRect.x - 1) - getTickSize(), r.y );
  334.         }
  335.         else {
  336.             r.setLocation((r.x + (r.width - 1)) - getTickSize(), r.y);
  337.         }
  338.         r.setSize(getTickSize(), r.height);
  339.         } else {
  340.             if ( slider.getPaintLabels() ) {
  341.             r.setLocation( r.x, (labelRect.y - 1) - getTickSize() );
  342.         }
  343.         else {
  344.             r.setLocation(r.x, (r.y + (r.height - 1)) - getTickSize());
  345.         }
  346.         r.setSize(r.width, getTickSize());
  347.         }
  348.      } else {
  349.         r.setLocation( labelRect.x, labelRect.y );
  350.  
  351.         if(slider.getOrientation() == JSlider.VERTICAL)  {
  352.         r.setSize( 0, r.height );
  353.         }
  354.         else {
  355.             r.setSize( r.width, 0 );
  356.         }
  357.     }
  358.  
  359.     return r;
  360.     }
  361.  
  362.     public Rectangle getLabelRect() {
  363.         return labelRect;
  364.     }
  365.  
  366.     protected void recalcLabelRect() {
  367.         Rectangle interior = getFullContentArea();
  368.  
  369.         if ( slider.getPaintLabels() ) {
  370.         if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  371.             int maxLabelHeight = getHeightOfTallestLabel();
  372.             interior.y = (interior.y + (interior.height - 1)) - maxLabelHeight;
  373.         interior.height = maxLabelHeight;
  374.         }
  375.         else {
  376.             int maxLabelWidth = getWidthOfWidestLabel();
  377.             interior.x = (interior.x + (interior.width - 1)) - maxLabelWidth;
  378.         interior.width = maxLabelWidth;
  379.         }
  380.     }
  381.     else {
  382.         if(slider.getOrientation() == JSlider.VERTICAL)  {
  383.         interior.setLocation( interior.x + (interior.width - 1), interior.y  );
  384.         interior.setSize( 0, interior.height );
  385.         }
  386.         else {
  387.         interior.setLocation( interior.x, interior.y + (interior.height - 1) );
  388.         interior.setSize( interior.width, 0 );
  389.         }
  390.     }
  391.  
  392.     labelRect = interior;
  393.     }
  394.  
  395.     public void propertyChange( PropertyChangeEvent evt ) {
  396.         if ( evt.getPropertyName().equals( "labelTable" ) ) {
  397.         recalcLabelRect();
  398.         recalcTrackBuffer();
  399.     }
  400.     }
  401.  
  402.     protected void recalcTrackBuffer() {
  403.         if ( slider.getPaintLabels() && slider.getLabelTable()  != null ) {
  404.         Component highLabel = getHighestValueLabel();
  405.         Component lowLabel = getLowestValueLabel();
  406.  
  407.         if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  408.             trackBuffer = Math.max( highLabel.getBounds().width, lowLabel.getBounds().width ) / 2;
  409.         trackBuffer = Math.max( trackBuffer, getThumbRect().width / 2 );
  410.         }
  411.         else {
  412.             trackBuffer = Math.max( highLabel.getBounds().height, lowLabel.getBounds().height ) / 2;
  413.         trackBuffer = Math.max( trackBuffer, getThumbRect().height / 2 );
  414.         }
  415.     }
  416.     else {
  417.         if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  418.             trackBuffer = getThumbRect().width / 2;
  419.         }
  420.         else {
  421.             trackBuffer = getThumbRect().height / 2;
  422.         }
  423.     }
  424.     }
  425.  
  426.     protected int getWidthOfWidestLabel() {
  427.         Dictionary dictionary = slider.getLabelTable();
  428.     int widest = 0;
  429.     if ( dictionary != null ) {
  430.         Enumeration keys = dictionary.keys();
  431.         while ( keys.hasMoreElements() ) {
  432.             Component label = (Component)dictionary.get( keys.nextElement() );
  433.             widest = Math.max( label.getPreferredSize().width, widest );
  434.         }
  435.     }
  436.     return widest;
  437.     }
  438.  
  439.     protected int getHeightOfTallestLabel() {
  440.         Dictionary dictionary = slider.getLabelTable();
  441.     int tallest = 0;
  442.     if ( dictionary != null ) {
  443.         Enumeration keys = dictionary.keys();
  444.         while ( keys.hasMoreElements() ) {
  445.             Component label = (Component)dictionary.get( keys.nextElement() );
  446.         tallest = Math.max( label.getPreferredSize().height, tallest );
  447.         }
  448.     }
  449.     return tallest;
  450.     }
  451.  
  452.     protected int getWidthOfHighValueLabel() {
  453.         Component label = getHighestValueLabel();
  454.     int width = 0;
  455.  
  456.     if ( label != null ) {
  457.         width = label.getPreferredSize().width;
  458.     }
  459.  
  460.     return width;
  461.     }
  462.  
  463.     protected int getWidthOfLowValueLabel() {
  464.         Component label = getLowestValueLabel();
  465.     int width = 0;
  466.  
  467.     if ( label != null ) {
  468.         width = label.getPreferredSize().width;
  469.     }
  470.  
  471.     return width;
  472.     }
  473.  
  474.     protected int getHeightOfHighValueLabel() {
  475.         Component label = getHighestValueLabel();
  476.     int height = 0;
  477.  
  478.     if ( label != null ) {
  479.         height = label.getPreferredSize().height;
  480.     }
  481.  
  482.     return height;
  483.     }
  484.  
  485.     protected int getHeightOfLowValueLabel() {
  486.         Component label = getLowestValueLabel();
  487.     int height = 0;
  488.  
  489.     if ( label != null ) {
  490.         height = label.getPreferredSize().height;
  491.     }
  492.  
  493.     return height;
  494.     }
  495.  
  496.     /**
  497.      * Returns the label that corresponds to the highest slider value in the label table.
  498.      * @see JSlider#setLabelTable
  499.      */
  500.     protected Component getLowestValueLabel() {
  501.         Dictionary dictionary = slider.getLabelTable();
  502.     Component label = null;
  503.  
  504.     if ( dictionary != null ) {
  505.         Enumeration keys = dictionary.keys();
  506.         if ( keys.hasMoreElements() ) {
  507.             int lowestValue = ((Integer)keys.nextElement()).intValue();
  508.  
  509.         while ( keys.hasMoreElements() ) {
  510.             int value = ((Integer)keys.nextElement()).intValue();
  511.             lowestValue = Math.min( value, lowestValue );
  512.         }
  513.         
  514.         label = (Component)dictionary.get( new Integer( lowestValue ) );
  515.         }
  516.     }
  517.  
  518.     return label;
  519.     }
  520.  
  521.     /**
  522.      * Returns the label that corresponds to the lowest slider value in the label table.
  523.      * @see JSlider#setLabelTable
  524.      */
  525.     protected Component getHighestValueLabel() {
  526.         Dictionary dictionary = slider.getLabelTable();
  527.     Component label = null;
  528.  
  529.     if ( dictionary != null ) {
  530.         Enumeration keys = dictionary.keys();
  531.         if ( keys.hasMoreElements() ) {
  532.             int highestValue = ((Integer)keys.nextElement()).intValue();
  533.  
  534.         while ( keys.hasMoreElements() ) {
  535.             int value = ((Integer)keys.nextElement()).intValue();
  536.             highestValue = Math.max( value, highestValue );
  537.         }
  538.  
  539.         label = (Component)dictionary.get( new Integer( highestValue ) );
  540.         }
  541.     }
  542.  
  543.     return label;
  544.     }
  545.  
  546.     public int getTickSpace() {
  547.     return TICK_SPACE;
  548.     }
  549.     
  550.     public int getTickSize() {
  551.     return getTickSpace();
  552.     }
  553.                             
  554.     public void paint(Graphics g, JComponent c)   {
  555.     paintTrack(g);
  556.     if ( slider.getPaintTicks() ) {
  557.         paintTicks(g);
  558.     }
  559.     if ( slider.getPaintLabels() ) {
  560.         paintLabels(g);
  561.     }
  562.     paintFocus(g);        
  563.     paintThumb(g);
  564.     }
  565.  
  566.     public void paintFocus(Graphics g)  {        
  567.         if (slider.hasFocus()) {
  568.         /// PENDING(klobad) copied from Button code - fix when 2D available
  569.             // Draw each dash of the line pixel by pixel.
  570.             // The performance of this is surely poor -- Be sure
  571.             // to rewrite when 2d graphics package is ready.
  572.         Rectangle r = slider.getBounds();
  573.         r.x = 0;
  574.             r.y = 0;        
  575.         if(slider.getBorder() != null) {
  576.              r = getFullContentArea();
  577.         } 
  578.             g.setColor(getFocusColor());
  579.             BasicGraphicsUtils.drawDashedRect(g, r.x + 1, r.y + 1, r.width - 2, r.height - 2);
  580.         }
  581.     }
  582.  
  583.     public void paintTrack(Graphics g)  {        
  584.     int cx, cy, cw, ch;
  585.     int pad;
  586.  
  587.     Rectangle trackBounds = getScrollTrackRect();
  588.     
  589.     if(slider.getOrientation() == JSlider.HORIZONTAL)    {
  590.         pad = trackBuffer;
  591.         cx = pad;
  592.         cy = (trackBounds.height / 2) - 2;
  593.         cw = trackBounds.width - (trackBuffer * 2);
  594.         g.translate(trackBounds.x + cx, trackBounds.y + cy);
  595.         g.setColor(getShadowColor());
  596.         g.drawLine(0, 0, cw - 1, 0);
  597.         g.drawLine(0, 1, 0, 2);
  598.         g.setColor(getHighlightColor());
  599.         g.drawLine(0, 3, cw, 3);
  600.         g.drawLine(cw, 0, cw, 3);
  601.         g.setColor(Color.black);
  602.         g.drawLine(1, 1, cw-2, 1);
  603.     } else {
  604.         pad = trackBuffer;
  605.         cx = (trackBounds.width / 2) - 2;
  606.         cy = pad;
  607.         ch = trackBounds.height - (trackBuffer * 2);
  608.         g.translate(trackBounds.x + cx, trackBounds.y + cy);
  609.         g.setColor(getShadowColor());
  610.         g.drawLine(0, 0, 0, ch - 1);
  611.         g.drawLine(1, 0, 2, 0);
  612.         g.setColor(getHighlightColor());
  613.         g.drawLine(3, 0, 3, ch);
  614.         g.drawLine(0, ch, 3, ch);
  615.         g.setColor(Color.black);
  616.         g.drawLine(1, 1, 1, ch-2);
  617.     }
  618.  
  619.         g.translate(-(trackBounds.x + cx), -(trackBounds.y + cy));    
  620.     }
  621.  
  622.     public void paintTicks(Graphics g)  {        
  623.     Rectangle tickBounds = getScrollTickRect();
  624.  
  625.     int i;
  626.     int maj, min, max;
  627.     int w = tickBounds.width;
  628.     int h = tickBounds.height;
  629.     int centerEffect, tickHeight;
  630.  
  631.     g.translate(tickBounds.x, tickBounds.y);
  632.         g.setColor(slider.getBackground());
  633.         g.fillRect(0, 0, tickBounds.width, tickBounds.height);    
  634.     g.setColor(Color.black);
  635.  
  636.     maj = slider.getMajorTickSpacing();
  637.     min = slider.getMinorTickSpacing();
  638.  
  639.     if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  640.         int value = slider.getMinimum();
  641.         int xPos = 0;
  642.         
  643.         if ( slider.getMinorTickSpacing() > 0 ) {
  644.             while ( value <= slider.getMaximum() ) {
  645.             xPos = xPositionForValue( value );
  646.             paintMinorTickForHorizSlider( g, tickBounds, xPos );
  647.             value += slider.getMinorTickSpacing();
  648.         }
  649.         }
  650.  
  651.         if ( slider.getMajorTickSpacing() > 0 ) {
  652.             value = slider.getMinimum();
  653.  
  654.         while ( value <= slider.getMaximum() ) {
  655.             xPos = xPositionForValue( value );
  656.             paintMajorTickForHorizSlider( g, tickBounds, xPos );
  657.             value += slider.getMajorTickSpacing();
  658.         }
  659.         }
  660.     }
  661.     else {
  662.         int value = slider.getMinimum();
  663.         int yPos = 0;
  664.         
  665.         if ( slider.getMinorTickSpacing() > 0 ) {
  666.             while ( value <= slider.getMaximum() ) {
  667.             yPos = yPositionForValue( value );
  668.             paintMinorTickForVertSlider( g, tickBounds, yPos );
  669.             value += slider.getMinorTickSpacing();
  670.         }
  671.         }
  672.  
  673.         if ( slider.getMajorTickSpacing() > 0 ) {
  674.             value = slider.getMinimum();
  675.  
  676.         while ( value <= slider.getMaximum() ) {
  677.             yPos = yPositionForValue( value );
  678.             paintMajorTickForVertSlider( g, tickBounds, yPos );
  679.             value += slider.getMajorTickSpacing();
  680.         }
  681.         }
  682.     }
  683.  
  684.     g.translate(-tickBounds.x, -tickBounds.y);
  685.     }
  686.  
  687.     protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
  688.         g.drawLine( x, 0, x, tickBounds.height / 2 - 1 );
  689.     }
  690.  
  691.     protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
  692.         g.drawLine( x, 0, x, tickBounds.height - 2 );
  693.     }
  694.  
  695.     protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
  696.         g.drawLine( 0, y, tickBounds.width / 2 - 1, y );
  697.     }
  698.  
  699.     protected void paintMajorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
  700.         g.drawLine( 0, y,  tickBounds.width - 2, y );
  701.     }
  702.  
  703.     public void paintLabels( Graphics g ) {
  704.         Rectangle labelBounds = getLabelRect();
  705.  
  706.     g.translate( labelBounds.x, labelBounds.y );
  707.  
  708.     Dictionary dictionary = slider.getLabelTable();
  709.     if ( dictionary != null ) {
  710.         Enumeration keys = dictionary.keys();
  711.         while ( keys.hasMoreElements() ) {
  712.             Integer key = (Integer)keys.nextElement();
  713.         Component label = (Component)dictionary.get( key );
  714.  
  715.             if ( slider.getOrientation() == JSlider.HORIZONTAL ) {
  716.             paintHorizontalLabel( g, key.intValue(), label );
  717.         }
  718.         else {
  719.             paintVerticalLabel( g, key.intValue(), label );
  720.         }
  721.         }
  722.     }
  723.  
  724.     g.translate( -labelBounds.x, -labelBounds.y );
  725.     }
  726.  
  727.     /**
  728.      * Called for every label in the label table.  Used to draw the labels for horizontal sliders.
  729.      * The graphics have been translated to the label rect already.
  730.      * @see JSlider#setLabelTable
  731.      */
  732.     protected void paintHorizontalLabel( Graphics g, int value, Component label ) {
  733.         int labelCenter = xPositionForValue( value );
  734.     int labelLeft = labelCenter - (label.getPreferredSize().width / 2);
  735.     g.translate( labelLeft, 0 );
  736.     label.paint( g );
  737.     g.translate( -labelLeft, 0 );
  738.     }
  739.  
  740.     /**
  741.      * Called for every label in the label table.  Used to draw the labels for vertical sliders.
  742.      * The graphics have been translated to the label rect already.
  743.      * @see JSlider#setLabelTable
  744.      */
  745.     protected void paintVerticalLabel( Graphics g, int value, Component label ) {
  746.         int labelCenter = yPositionForValue( value );
  747.     int labelTop = labelCenter - (label.getPreferredSize().height / 2);
  748.     g.translate( 0, labelTop );
  749.     label.paint( g );
  750.     g.translate( 0, -labelTop );
  751.     }
  752.  
  753.     public void paintThumb(Graphics g)  {        
  754.     Rectangle knobBounds = getThumbRect();
  755.         int w = knobBounds.width;
  756.         int h = knobBounds.height;        
  757.     
  758.     g.translate(knobBounds.x, knobBounds.y);
  759.  
  760.     if(slider.isEnabled()) {
  761.         g.setColor(slider.getBackground());
  762.     } else {
  763.         g.setColor(slider.getBackground().darker());
  764.     }
  765.  
  766.     if(!slider.getPaintTicks()) {
  767.         g.fillRect(0, 0, w, h);
  768.  
  769.         g.setColor(Color.black);
  770.         g.drawLine(0, h-1, w-1, h-1);    
  771.         g.drawLine(w-1, 0, w-1, h-1);    
  772.     
  773.         g.setColor(BasicGraphicsUtils.controlHighlight);
  774.         g.drawLine(0, 0, 0, h-2);
  775.         g.drawLine(1, 0, w-2, 0);
  776.     
  777.         g.setColor(BasicGraphicsUtils.controlShadow);
  778.         g.drawLine(1, h-2, w-2, h-2);
  779.         g.drawLine(w-2, 1, w-2, h-3);
  780.     } else if (slider.getOrientation() == JSlider.HORIZONTAL ) {
  781.         int cw = w / 2;
  782.         g.fillRect(1, 1, w-3, h-1-cw);
  783.         Polygon p = new Polygon();
  784.         p.addPoint(1, h-cw);
  785.         p.addPoint(cw-1, h-1);
  786.         p.addPoint(w-2, h-1-cw);
  787.             g.fillPolygon(p);        
  788.  
  789.         g.setColor(BasicGraphicsUtils.controlHighlight);
  790.         g.drawLine(0, 0, w-2, 0);
  791.         g.drawLine(0, 1, 0, h-1-cw);
  792.         g.drawLine(0, h-cw, cw-1, h-1); 
  793.  
  794.         g.setColor(Color.black);
  795.         g.drawLine(w-1, 0, w-1, h-2-cw);    
  796.         g.drawLine(w-1, h-1-cw, w-1-cw, h-1);        
  797.     
  798.         g.setColor(BasicGraphicsUtils.controlShadow);
  799.         g.drawLine(w-2, 1, w-2, h-2-cw);    
  800.         g.drawLine(w-2, h-1-cw, w-1-cw, h-2);        
  801.     } else {
  802.         int cw = h / 2;
  803.         g.fillRect(1, 1, w-1-cw, h-3);
  804.         Polygon p = new Polygon();
  805.         p.addPoint(w-cw-1, 0);
  806.         p.addPoint(w-1, cw);
  807.         p.addPoint(w-1-cw, h-2);
  808.             g.fillPolygon(p);        
  809.  
  810.         g.setColor(BasicGraphicsUtils.controlHighlight);
  811.         g.drawLine(0, 0, 0, h - 2);
  812.         g.drawLine(1, 0, w-1-cw, 0);
  813.         g.drawLine(w-cw-1, 0, w-1, cw); 
  814.  
  815.         g.setColor(Color.black);
  816.         g.drawLine(0, h-1, w-2-cw, h-1);    
  817.         g.drawLine(w-1-cw, h-1, w-1, h-1-cw);        
  818.     
  819.         g.setColor(BasicGraphicsUtils.controlShadow);
  820.         g.drawLine(1, h-2, w-2-cw,  h-2 );    
  821.         g.drawLine(w-1-cw, h-2, w-2, h-cw-1 );        
  822.     }
  823.  
  824.     g.translate(-knobBounds.x, -knobBounds.y);
  825.     }
  826.         
  827.     public void setThumbBounds(int x, int y, int width, int height)    {
  828.     Rectangle r = new Rectangle(thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height);
  829.     Rectangle r2;
  830.  
  831.     thumbRect.setBounds(x, y, width, height);
  832.  
  833.     r2 = r.union(thumbRect);
  834.     slider.repaint(r2.x, r2.y, r2.width, r2.height);
  835.     }
  836.  
  837.     public void setThumbLocation(int x, int y)    {
  838.     Rectangle r = new Rectangle(thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height);
  839.     Rectangle r2;
  840.  
  841.     thumbRect.setLocation(x, y);
  842.  
  843.     r2 = r.union(thumbRect);
  844.     slider.repaint(r2.x, r2.y, r2.width, r2.height);
  845.     }
  846.  
  847.     public Rectangle getThumbRect()    {
  848.     return thumbRect;
  849.     }
  850.  
  851.     public void scrollByBlock(int direction)    {
  852.     synchronized(slider)    {
  853.     
  854.     int oldValue = slider.getValue();
  855.     int blockIncrement = slider.getMaximum() / 10;
  856.     int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
  857.  
  858.     slider.setValue(oldValue + delta);            
  859.     }
  860.     }
  861.  
  862.     public void scrollByUnit(int direction)    {
  863.     synchronized(slider)    {
  864.     
  865.     int oldValue = slider.getValue();
  866.     int delta = 1 * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
  867.  
  868.     slider.setValue(oldValue + delta);    
  869.         }        
  870.     }
  871.  
  872.     /**
  873.      * This function is called when a mousePressed was detected in the track, not
  874.      * in the thumb.  The default behavior is to scroll by block.  You can
  875.      *  override this method to stop it from scrolling or to add additional behavior.
  876.      */
  877.     protected void scrollDueToClickInTrack( int dir ) {
  878.         scrollByBlock( dir );
  879.     }
  880.  
  881.     protected int xPositionForValue(int randomValue)    {
  882.         int min = slider.getMinimum();
  883.     int max = slider.getMaximum();
  884.     Rectangle trackRect = getScrollTrackRect();        
  885.     int trackLength = trackRect.width - (trackBuffer * 2);
  886.     int valueRange = slider.getMaximum() - slider.getMinimum();
  887.     double pixelsPerValue = (double)trackLength / (double)valueRange;
  888.     int trackLeft = trackRect.x + trackBuffer;
  889.     int trackRight = (trackRect.x + (trackRect.width - 1)) - trackBuffer;
  890.     int xPosition;
  891.     
  892.     if ( !slider.getInverted() ) {
  893.         xPosition = trackLeft;
  894.         xPosition += Math.round( pixelsPerValue * (double)(randomValue - min) );
  895.     }
  896.     else {
  897.         xPosition = trackRight;
  898.         xPosition -= Math.round( pixelsPerValue * (double)(randomValue - min) );
  899.     }
  900.  
  901.     xPosition = Math.max( trackLeft, xPosition );
  902.     xPosition = Math.min( trackRight, xPosition );
  903.  
  904.     return xPosition;
  905.     }
  906.  
  907.     protected int yPositionForValue(int randomValue)  {
  908.         int min = slider.getMinimum();
  909.     int max = slider.getMaximum();
  910.     Rectangle trackRect = getScrollTrackRect();        
  911.     int trackLength = trackRect.height - (trackBuffer * 2);
  912.     int valueRange = slider.getMaximum() - slider.getMinimum();
  913.     double pixelsPerValue = (double)trackLength / (double)valueRange;
  914.     int trackTop = trackRect.y + trackBuffer;
  915.     int trackBottom = (trackRect.y + (trackRect.height - 1)) - trackBuffer;
  916.     int yPosition;
  917.     
  918.     if ( !slider.getInverted() ) {
  919.         yPosition = trackTop;
  920.         yPosition += Math.round( pixelsPerValue * (double)(max - randomValue ) );
  921.     }
  922.     else {
  923.         yPosition = trackTop;
  924.         yPosition += Math.round( pixelsPerValue * (double)(randomValue - min) );
  925.     }
  926.  
  927.     yPosition = Math.max( trackTop, yPosition );
  928.     yPosition = Math.min( trackBottom, yPosition );
  929.  
  930.     return yPosition;
  931.     }
  932.  
  933.     public void calculateThumbBounds()    {
  934.     if(slider.getOrientation() == JSlider.VERTICAL)    {
  935.         setThumbBounds(getScrollTrackRect().x, yPositionForValue(slider.getValue()) - getThumbRect().height / 2,
  936.                getScrollTrackRect().width, 11);
  937.     } else {
  938.         setThumbBounds(xPositionForValue(slider.getValue()) - getThumbRect().width / 2,
  939.                getScrollTrackRect().y, 
  940.                11, getScrollTrackRect().height);
  941.     }
  942.     }
  943.  
  944.           
  945.     /////////////////////////////////////////////////////////////////////////
  946.     /// Model Listener Class
  947.     /////////////////////////////////////////////////////////////////////////        
  948.     /**
  949.      * Data model listener.
  950.      * <p>
  951.      * Warning: serialized objects of this class will not be compatible with
  952.      * future swing releases.  The current serialization support is appropriate
  953.      * for short term storage or RMI between Swing1.0 applications.  It will
  954.      * not be possible to load serialized Swing1.0 objects with future releases
  955.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  956.      * baseline for the serialized form of Swing objects.
  957.      */
  958.     protected class ModelListener implements ChangeListener,Serializable            {
  959.         public void stateChanged(ChangeEvent e)                {
  960.         if(!isDragging)    
  961.         calculateThumbBounds();
  962.         }
  963.     }
  964.                
  965.     /////////////////////////////////////////////////////////////////////////
  966.     /// Track Listener Class
  967.     /////////////////////////////////////////////////////////////////////////        
  968.     /**
  969.      * Track mouse movements.
  970.      * <p>
  971.      * Warning: serialized objects of this class will not be compatible with
  972.      * future swing releases.  The current serialization support is appropriate
  973.      * for short term storage or RMI between Swing1.0 applications.  It will
  974.      * not be possible to load serialized Swing1.0 objects with future releases
  975.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  976.      * baseline for the serialized form of Swing objects.
  977.      */
  978.     protected class TrackListener extends MouseAdapter
  979.                 implements MouseMotionListener, Serializable    {
  980.     protected transient int offset;
  981.     protected transient int currentMouseX, currentMouseY;
  982.         
  983.         public void mouseReleased(MouseEvent e)                {
  984.         if(!slider.isEnabled())
  985.         return;
  986.  
  987.         offset = 0;
  988.         scrollTimer.stop();
  989.  
  990.         // This is the way we have to determine snap-to-ticks.  It's hard to explain
  991.         // but since ChangeEvents don't give us any idea what has changed we don't
  992.         // have a way to stop the thumb bounds from being recalculated.  Recalculating
  993.         // the thumb bounds moves the thumb over the current value (i.e., snapping
  994.         // to the ticks).
  995.         if ( slider.getSnapToTicks() ) {
  996.         isDragging = false;
  997.             slider.setValueIsAdjusting(false);
  998.         }
  999.         else {
  1000.             slider.setValueIsAdjusting(false);
  1001.         isDragging = false;
  1002.         }
  1003.     }
  1004.         
  1005.         /**
  1006.         * If the mouse is pressed above the "thumb" component
  1007.         * then reduce the scrollbars value by one page ("page up"), 
  1008.         * otherwise increase it by one page.  If there is no 
  1009.         * thumb then page up if the mouse is in the upper half
  1010.         * of the track.
  1011.         */
  1012.         public void mousePressed(MouseEvent e)                {
  1013.  
  1014.         if(!slider.isEnabled())
  1015.         return;
  1016.  
  1017.             currentMouseX = e.getX();
  1018.             currentMouseY = e.getY();
  1019.  
  1020.         slider.requestFocus();
  1021.     
  1022.         // Clicked in the Thumb area?
  1023.         if(getThumbRect().contains(currentMouseX, currentMouseY))    {
  1024.                 switch (slider.getOrientation()) {
  1025.                 case JSlider.VERTICAL:
  1026.             offset = currentMouseY - getThumbRect().y;
  1027.                     break;
  1028.                 case JSlider.HORIZONTAL:
  1029.             offset = currentMouseX - getThumbRect().x;
  1030.                     break;
  1031.                 }
  1032.         isDragging = true;
  1033.         slider.setValueIsAdjusting(true);
  1034.         return;
  1035.         }            
  1036.         isDragging = false;
  1037.         slider.setValueIsAdjusting(true);
  1038.                             
  1039.             Dimension sbSize = slider.getSize();
  1040.             int direction = POSITIVE_SCROLL;
  1041.  
  1042.             switch (slider.getOrientation()) {
  1043.             case JSlider.VERTICAL:
  1044.                 if (getThumbRect().isEmpty()) {
  1045.                     int scrollbarCenter = sbSize.height / 2;
  1046.             if ( !slider.getInverted() ) {
  1047.                 direction = (currentMouseY < scrollbarCenter) ? POSITIVE_SCROLL : NEGATIVE_SCROLL;
  1048.             }
  1049.             else {
  1050.                 direction = (currentMouseY < scrollbarCenter) ? NEGATIVE_SCROLL : POSITIVE_SCROLL;
  1051.             }
  1052.                 } else {
  1053.                     int thumbY = getThumbRect().y;
  1054.             if ( !slider.getInverted() ) {
  1055.                 direction = (currentMouseY < thumbY) ? POSITIVE_SCROLL : NEGATIVE_SCROLL;
  1056.             }
  1057.             else {
  1058.                 direction = (currentMouseY < thumbY) ? NEGATIVE_SCROLL : POSITIVE_SCROLL;
  1059.             }
  1060.                 }
  1061.                 break;                    
  1062.             case JSlider.HORIZONTAL:
  1063.                 if (getThumbRect().isEmpty()) {
  1064.                     int scrollbarCenter = sbSize.width / 2;
  1065.             if ( !slider.getInverted() ) {
  1066.                 direction = (currentMouseX < scrollbarCenter) ? NEGATIVE_SCROLL : POSITIVE_SCROLL;
  1067.             }
  1068.             else {
  1069.                 direction = (currentMouseX < scrollbarCenter) ? POSITIVE_SCROLL : NEGATIVE_SCROLL;
  1070.             }
  1071.                 } else {
  1072.                     int thumbX = getThumbRect().x;
  1073.             if ( !slider.getInverted() ) {
  1074.                 direction = (currentMouseX < thumbX) ? NEGATIVE_SCROLL : POSITIVE_SCROLL;
  1075.             }
  1076.             else {
  1077.                 direction = (currentMouseX < thumbX) ? POSITIVE_SCROLL : NEGATIVE_SCROLL;
  1078.             }
  1079.                 }
  1080.                 break;
  1081.             }
  1082.         scrollDueToClickInTrack(direction);
  1083.         Rectangle r = getThumbRect();
  1084.         if(!r.contains(currentMouseX, currentMouseY))    {
  1085.         if(shouldScroll(direction)) {
  1086.             scrollTimer.stop();
  1087.             scrollListener.setDirection(direction);
  1088.             scrollTimer.start();
  1089.         }
  1090.         }
  1091.         }
  1092.  
  1093.     public boolean shouldScroll(int direction) {
  1094.         Rectangle r = getThumbRect();
  1095.         if(slider.getOrientation() == JSlider.VERTICAL) {
  1096.             if(slider.getInverted() ? direction < 0 : direction > 0)    {
  1097.             if(r.y + r.height  <= currentMouseY) {
  1098.                 return false;
  1099.             }
  1100.         }
  1101.         else if(r.y >= currentMouseY) {
  1102.             return false;
  1103.         }
  1104.         } else {
  1105.         if( slider.getInverted() ? direction < 0 : direction > 0)    {
  1106.             if(r.x + r.width  >= currentMouseX) {
  1107.                 return false;
  1108.             }
  1109.         } else if(r.x <= currentMouseX)    {
  1110.             return false;
  1111.         }
  1112.         }
  1113.  
  1114.         if(direction > 0 && slider.getValue() + slider.getExtent() >= slider.getMaximum()) {
  1115.             return false;
  1116.         }
  1117.         else if(direction < 0 && slider.getValue() <= slider.getMinimum()) {
  1118.             return false;
  1119.         }
  1120.     
  1121.         return true;
  1122.     }
  1123.         
  1124.         /** 
  1125.         * Set the models value to the position of the top/left
  1126.         * of the thumb relative to the origin of the track.
  1127.         */
  1128.         public void mouseDragged(MouseEvent e)                 {                    
  1129.         BasicScrollBarUI ui;
  1130.         int centerEffect;
  1131.         Rectangle scrollTrackRect = getScrollTrackRect();
  1132.         int thumbMiddle = 0;
  1133.  
  1134.         if(!slider.isEnabled())
  1135.         return;
  1136.  
  1137.             currentMouseX = e.getX();
  1138.             currentMouseY = e.getY();
  1139.  
  1140.         if(!isDragging)
  1141.         return;
  1142.  
  1143.             switch (slider.getOrientation()) {
  1144.             case JSlider.VERTICAL:        
  1145.             int halfThumbHeight = getThumbRect().height / 2;
  1146.         int thumbTop = e.getY() - offset;
  1147.         int trackTop = scrollTrackRect.y + trackBuffer;
  1148.         int trackBottom = (scrollTrackRect.y + (scrollTrackRect.height - 1)) - trackBuffer;
  1149.  
  1150.         thumbTop = Math.max( thumbTop, trackTop - halfThumbHeight );
  1151.         thumbTop = Math.min( thumbTop, trackBottom - halfThumbHeight );
  1152.  
  1153.         setThumbLocation(getThumbRect().x, thumbTop);
  1154.  
  1155.         thumbMiddle = thumbTop + halfThumbHeight;
  1156.         slider.setValue( valueForYPosition( thumbMiddle ) );
  1157.                 break;
  1158.             case JSlider.HORIZONTAL:
  1159.             int halfThumbWidth = getThumbRect().width / 2;
  1160.         int thumbLeft = e.getX() - offset;
  1161.         int trackLeft = scrollTrackRect.x + trackBuffer;
  1162.         int trackRight = (scrollTrackRect.x + (scrollTrackRect.width - 1)) - trackBuffer;
  1163.  
  1164.         thumbLeft = Math.max( thumbLeft, trackLeft - halfThumbWidth );
  1165.         thumbLeft = Math.min( thumbLeft, trackRight - halfThumbWidth );
  1166.  
  1167.         setThumbLocation( thumbLeft, getThumbRect().y);
  1168.  
  1169.         thumbMiddle = thumbLeft + halfThumbWidth;
  1170.         slider.setValue( valueForXPosition( thumbMiddle ) );
  1171.                 break;
  1172.             default:
  1173.                 return;
  1174.             }
  1175.         }
  1176.         
  1177.     public void mouseMoved(MouseEvent e)    {}     
  1178.  
  1179.     /**
  1180.      * Returns a value give a y position.  If yPos is past the track at the top or the
  1181.      * bottom it will set the value to the min or max of the slider, depending if the
  1182.      * slider is inverted or not.
  1183.      */
  1184.         public int valueForYPosition( int yPos ) {
  1185.         int value;
  1186.         final int minValue = slider.getMinimum();
  1187.         final int maxValue = slider.getMaximum();
  1188.         final Rectangle trackRect = getScrollTrackRect();
  1189.         final int trackLength = trackRect.height - (trackBuffer * 2);
  1190.         final int trackTop = trackRect.y + trackBuffer;
  1191.         final int trackBottom = (trackRect.y + (trackRect.height - 1)) - trackBuffer;
  1192.         
  1193.         if ( yPos <= trackTop ) {
  1194.             value = slider.getInverted() ? minValue : maxValue;
  1195.         }
  1196.         else if ( yPos >= trackBottom ) {
  1197.             value = slider.getInverted() ? maxValue : minValue;
  1198.         }
  1199.         else {
  1200.             int distanceFromTrackTop = yPos - trackTop;
  1201.         int valueRange = maxValue - minValue;
  1202.         double valuePerPixel = (double)valueRange / (double)trackLength;
  1203.         int valueFromTrackTop = (int)Math.round( distanceFromTrackTop * valuePerPixel );
  1204.  
  1205.         value = slider.getInverted() ? minValue + valueFromTrackTop : maxValue - valueFromTrackTop;
  1206.         }
  1207.  
  1208.         return value;
  1209.     }
  1210.  
  1211.     /**
  1212.      * Returns a value give an x position.  If xPos is past the track at the left or the
  1213.      * right it will set the value to the min or max of the slider, depending if the
  1214.      * slider is inverted or not.
  1215.      */
  1216.         public int valueForXPosition( int xPos ) {
  1217.         int value;
  1218.         final int minValue = slider.getMinimum();
  1219.         final int maxValue = slider.getMaximum();
  1220.         final Rectangle trackRect = getScrollTrackRect();
  1221.         final int trackLength = trackRect.width - (trackBuffer * 2);
  1222.         final int trackLeft = trackRect.x + trackBuffer;
  1223.         final int trackRight = (trackRect.x + (trackRect.width - 1)) - trackBuffer;
  1224.         
  1225.         if ( xPos <= trackLeft ) {
  1226.             value = slider.getInverted() ? maxValue : minValue;
  1227.         }
  1228.         else if ( xPos >= trackRight ) {
  1229.             value = slider.getInverted() ? minValue : maxValue;
  1230.         }
  1231.         else {
  1232.             int distanceFromTrackLeft = xPos - trackLeft;
  1233.         int valueRange = maxValue - minValue;
  1234.         double valuePerPixel = (double)valueRange / (double)trackLength;
  1235.         int valueFromTrackLeft = (int)Math.round( distanceFromTrackLeft * valuePerPixel );
  1236.  
  1237.         value = slider.getInverted() ? maxValue - valueFromTrackLeft :
  1238.                                        minValue + valueFromTrackLeft;
  1239.         }
  1240.  
  1241.         return value;
  1242.     }
  1243.     }
  1244.  
  1245.     /**
  1246.      * Scroll-event listener.
  1247.      * <p>
  1248.      * Warning: serialized objects of this class will not be compatible with
  1249.      * future swing releases.  The current serialization support is appropriate
  1250.      * for short term storage or RMI between Swing1.0 applications.  It will
  1251.      * not be possible to load serialized Swing1.0 objects with future releases
  1252.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1253.      * baseline for the serialized form of Swing objects.
  1254.      */
  1255.     public class ScrollListener implements ActionListener, Serializable
  1256.     // changed this class to public to avoid bogus IllegalAccessException bug i
  1257.     // InternetExplorer browser.  It was protected.  Work around for 4109432
  1258.     {
  1259.     int direction = POSITIVE_SCROLL;
  1260.     boolean useBlockIncrement;
  1261.  
  1262.     public ScrollListener()    {
  1263.         direction = POSITIVE_SCROLL;
  1264.         useBlockIncrement = true;
  1265.     }
  1266.  
  1267.         public ScrollListener(int dir, boolean block)    {
  1268.         direction = dir;
  1269.         useBlockIncrement = block;
  1270.     }
  1271.     
  1272.     public void setDirection(int direction) { this.direction = direction; }
  1273.     public void setScrollByBlock(boolean block) { this.useBlockIncrement = block; }
  1274.                     
  1275.     public void actionPerformed(ActionEvent e) {
  1276.         if(useBlockIncrement)    {
  1277.         scrollByBlock(direction);
  1278.         }
  1279.         else {
  1280.         scrollByUnit(direction);
  1281.         }
  1282.             if(!trackListener.shouldScroll(direction)) {
  1283.             ((Timer)e.getSource()).stop();
  1284.         }
  1285.     }
  1286.     }; 
  1287.     
  1288.     /// Possible bug in ComponentListener.
  1289.     // I don't seem to be getting the resize events, only moves.
  1290.     // recalculate any time, just in case.
  1291.     /**
  1292.      * Listener for resizing events.
  1293.      * <p>
  1294.      * Warning: serialized objects of this class will not be compatible with
  1295.      * future swing releases.  The current serialization support is appropriate
  1296.      * for short term storage or RMI between Swing1.0 applications.  It will
  1297.      * not be possible to load serialized Swing1.0 objects with future releases
  1298.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1299.      * baseline for the serialized form of Swing objects.
  1300.      */
  1301.     protected class SizingListener implements ComponentListener, Serializable  {
  1302.     public void componentResized(ComponentEvent e)    {
  1303.         recalcLabelRect();
  1304.         calculateThumbBounds();
  1305.     }
  1306.     public void componentHidden(ComponentEvent e)    {
  1307.         recalcLabelRect();
  1308.         calculateThumbBounds();
  1309.     }
  1310.     public void componentMoved(ComponentEvent e)    {
  1311.         recalcLabelRect();
  1312.         calculateThumbBounds();
  1313.     }
  1314.     public void componentShown(ComponentEvent e)    {
  1315.         recalcLabelRect();
  1316.         calculateThumbBounds();
  1317.     }
  1318.     };    
  1319.  
  1320.     /**
  1321.      * Focus-change listener.
  1322.      * <p>
  1323.      * Warning: serialized objects of this class will not be compatible with
  1324.      * future swing releases.  The current serialization support is appropriate
  1325.      * for short term storage or RMI between Swing1.0 applications.  It will
  1326.      * not be possible to load serialized Swing1.0 objects with future releases
  1327.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1328.      * baseline for the serialized form of Swing objects.
  1329.      */
  1330.     protected class FListener implements FocusListener, Serializable  {
  1331.         public void focusGained(FocusEvent e) { slider.repaint(); }    
  1332.         public void focusLost(FocusEvent e) { slider.repaint(); }
  1333.     };
  1334.  
  1335.     /**
  1336.      * Defines the action to take when scrolled.
  1337.      * <p>
  1338.      * Warning: serialized objects of this class will not be compatible with
  1339.      * future swing releases.  The current serialization support is appropriate
  1340.      * for short term storage or RMI between Swing1.0 applications.  It will
  1341.      * not be possible to load serialized Swing1.0 objects with future releases
  1342.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1343.      * baseline for the serialized form of Swing objects.
  1344.      */
  1345.     protected class ActionScroller extends AbstractAction implements Serializable
  1346.     {
  1347.     int dir;
  1348.     boolean block;
  1349.         JSlider slider;
  1350.  
  1351.     public ActionScroller( JSlider slider, int dir, boolean block) {
  1352.         this.dir = dir;
  1353.         this.block = block;
  1354.         this.slider = slider;
  1355.     }
  1356.  
  1357.     public void actionPerformed(ActionEvent e) {
  1358.         if ( slider.isEnabled() ) {
  1359.             if(dir == NEGATIVE_SCROLL || dir == POSITIVE_SCROLL) {
  1360.             int realDir = dir;
  1361.             if ( slider.getInverted() ) {
  1362.                 realDir = dir == NEGATIVE_SCROLL ? POSITIVE_SCROLL : NEGATIVE_SCROLL;
  1363.             }
  1364.  
  1365.             if(block)
  1366.                 scrollByBlock(realDir);
  1367.             else 
  1368.                 scrollByUnit(realDir);
  1369.         } else {
  1370.             if ( slider.getInverted() ) {
  1371.                 if(dir == MIN_SCROLL)
  1372.                 slider.setValue(slider.getMaximum());            
  1373.             else if(dir == MAX_SCROLL)
  1374.               slider.setValue(slider.getMinimum());
  1375.             }
  1376.             else {
  1377.                 if(dir == MIN_SCROLL)
  1378.                 slider.setValue(slider.getMinimum());            
  1379.             else if(dir == MAX_SCROLL)
  1380.               slider.setValue(slider.getMaximum());
  1381.             }        
  1382.         }
  1383.         }
  1384.     }
  1385.  
  1386.     public boolean isEnabled() { return true; }
  1387.     };
  1388. }
  1389.  
  1390.